package com.example.rab.utils;

import com.google.zxing.*;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.springframework.core.io.ClassPathResource;
import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.Hashtable;

/**
 * @projectName: zzhMain
 * @package: com.example.rab.utils
 * @className: QRCodeUtil
 * @author: zzh
 * @description: TODO
 * @version: 1.0
 */
public class QrCodeUtils {
    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;
    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "JPG";
    // 二维码尺寸
    private static final int QRCODE_SIZE = 248;
    // 用二维码生成新图片，新图片加高多少，比如加的字体大小为24，这里就设置成26
    private static final int FONT_SIZE_HEIGHT = 20;
    // LOGO宽度
    private static final int WIDTH = 40;
    // LOGO高度
    private static final int HEIGHT = 40;



    //以下是生成样式二维码
    //创建二维码
    private static BufferedImage createImage(String content, String imgPath,String bg, boolean needCompress, String gunCode, String kw, String ab) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 5);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        if (imgPath == null || imgPath.isEmpty()) {
            return image;
        }
        // 插入图片
        QrCodeUtils.insertImage(image, imgPath, needCompress);
        image = QrCodeUtils.compoundImage(image, bg);
        QrCodeUtils.addFontImage(image, gunCode, 70,  485, 300, 20,24,248);
        QrCodeUtils.addFontImage(image, kw, 65, 270, 100, 28,28,100);
        QrCodeUtils.addFontImage(image, ab, 230, 270, 75, 28,28,75);
        return image;
    }

    private static BufferedImage compoundImage(BufferedImage source, String imgPath) throws IOException {
        //获取背景图片
        ClassPathResource classPathResource = new ClassPathResource(imgPath);
        InputStream inputStream = classPathResource.getInputStream();
        BufferedImage bg = ImageIO.read(inputStream);
        if (bg == null) {
            System.err.println(imgPath + "   无法读取为图片！");
        }
        // 插入二维码
        int height = bg.getHeight();//背景图片的高
        int width = bg.getWidth();  //背景图片的宽
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//创建画布
        Graphics g = img.getGraphics();//生成画笔 开启画图
        // 绘制背景图片
        g.drawImage(bg.getScaledInstance(width, height, Image.SCALE_DEFAULT), 0, 0, null); // 绘制缩小后的图
        //绘制二维码图片  定位到背景图的右下角
        g.drawImage(source.getScaledInstance(248, 248, Image.SCALE_DEFAULT), 65, 266, null); // 绘制缩小后的图
        //关掉画笔
        g.dispose();
        return img;
    }

    /**
     * 插入LOGO
     *
     * @param source       二维码图片
     * @param imgPath      LOGO图片地址
     * @param needCompress 是否压缩
     * @throws Exception
     */
    private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource("loge.pn");
        InputStream inputStream = classPathResource.getInputStream();
        Image src = ImageIO.read(inputStream);
        if (src == null) {
            System.err.println(imgPath + "   无法读取为图片！");
        }
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (needCompress) { // 压缩LOGO
            if (width > WIDTH) {
                width = WIDTH;
            }
            if (height > HEIGHT) {
                height = HEIGHT;
            }
            Image image = src.getScaledInstance(width, height,
                    Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            src = image;
        }
        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }

    /**
     * 插入文字
     *
     * @param source 二维码图片
     * @throws Exception
     */
    private static void addFontImage(BufferedImage source, String declareText, int wx, int wy, int width, int height ,int sizes,int b) throws Exception {
        //生成image
        BufferedImage textImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = (Graphics2D) textImage.getGraphics();
        //部署linux需要注意 linux无此字体会显示方块

//        ClassPathResource classPathResource = new ClassPathResource("simsun.ttf");
//        InputStream resourceAsStream = classPathResource.getInputStream();
//        //这个是设置字体样式和大小
//        //部署linux需要注意 linux无此字体会显示方块
//        Font font = Font.createFont(Font.TRUETYPE_FONT, resourceAsStream);
//        font = font.deriveFont(Font.BOLD, sizes);
        Font font = new Font("黑体", Font.BOLD, sizes);
        //开启文字抗锯齿
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
        g2.setBackground(Color.WHITE);

        g2.setStroke(new BasicStroke(10));
        g2.clearRect(0, 0, width, height);
        g2.setPaint(Color.BLACK);
        FontRenderContext context = g2.getFontRenderContext();
        g2.setFont(font);


        LineMetrics lineMetrics = font.getLineMetrics(declareText, context);
        FontMetrics fontMetrics = FontDesignMetrics.getMetrics(font);
        float offset = (float) (width - fontMetrics.stringWidth(declareText)) / 2;
        float y = (height + lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2;
        g2.drawString(declareText, (int) offset, (int) y);

        Graphics2D graph = source.createGraphics();
        //开启文字抗锯齿
        graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graph.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graph.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
        //添加image
        int heights = textImage.getHeight(null);

        Image src = textImage;
        graph.drawImage(src.getScaledInstance(b, heights, Image.SCALE_DEFAULT), wx, wy,  Color.WHITE, null);

        graph.dispose();
    }

    /**
     * 生成二维码(内嵌LOGO)
     *
     * @param content      内容
     * @param imgPath      LOGO地址
     * @param needCompress 是否压缩LOGO
     */
    public static byte[] encode(String content, String imgPath,String bg, boolean needCompress,String gunCode,String kw,String ab) throws Exception {
        byte[] bys = null;
        BufferedImage image = QrCodeUtils.createImage(content, imgPath,bg, needCompress,gunCode,kw,ab);
        ImageIO.write(image, "png", new File("d:\\a.png"));
//        ByteArrayOutputStream output = new ByteArrayOutputStream();
//        if (!ImageIO.write(image, "png", output)) {
//            throw new IOException("Could not write an image of format");
//        }
//        bys = output.toByteArray();
        return bys;
    }

    public static void main(String[] args) {
        String text = "晚安好无聊";  //这里设置自定义网站url
        String logoPath = "loge.png";
        try {
            QrCodeUtils.encode(text, logoPath,"mo.png",  true,"21","342324","342342");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
